package command

import (
	"errors"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime/debug"
	"strings"

	"gitee.com/gitee-go/core"
	"gitee.com/gitee-go/runner-core/comm"
	"gitee.com/gitee-go/runner-core/runner"
	"gitee.com/gitee-go/utils"
	"gopkg.in/yaml.v2"
)

const Version = "0.1.0"

type daemonCommand struct {
	path    string
	alias   string
	cmdconf comm.ExecerConfig
	conf    *comm.ExecerConfig

	limit int
}

func (c *daemonCommand) Alias() string {
	if c.alias == "" {
		c.alias = "default"
	}
	return c.alias
}
func (c *daemonCommand) config() error {
	println("config:" + c.Alias())
	mpcf := c.getFileConf()
	/*bts,_:=json.Marshal(mpcf)
	println("mpcf:",string(bts))*/
	cf, ok := mpcf[c.Alias()]
	if !ok || cf == nil {
		cf = &comm.ExecerConfig{}
	}
	if c.cmdconf.ServAddr != "" {
		cf.ServAddr = c.cmdconf.ServAddr
	}
	if c.cmdconf.Workspace != "" {
		cf.Workspace = c.cmdconf.Workspace
	}
	if c.cmdconf.Limit > 0 {
		cf.Limit = c.cmdconf.Limit
	}
	if c.cmdconf.Secret != "" {
		cf.Secret = c.cmdconf.Secret
	}
	hs, errhs := os.Hostname()
	if len(c.cmdconf.Plugin) > 0 {
		cf.Plugin = c.cmdconf.Plugin
	} else if errhs == nil && strings.Contains(hs, "@") {
		cf.Plugin = []string{hs}
	}
	if len(c.cmdconf.Env) > 0 {
		cf.Env = c.cmdconf.Env
	}
	cf.Name = c.Alias()
	if cf.ServAddr == "" {
		cf.ServAddr = utils.EnvDefault("SERVER_HOST", "server:7030")
	}
	if cf.Secret == "" {
		cf.Secret = utils.EnvDefault("RUNNER_SECRET")
	}
	if cf.Workspace == "" {
		//stat, err := os.Stat("/data")
		if errhs == nil && strings.Contains(hs, "@") {
			cf.Workspace = "/data"
		} else {
			cf.Workspace = c.path
		}
	}
	if len(cf.Plugin) <= 0 {
		cf.Plugin = []string{"shell@sh"}
	}

	mpcf[c.Alias()] = cf
	c.saveFileConf(mpcf)
	c.conf = cf
	return nil
}
func (c *daemonCommand) start() error {
	defer func() {
		if err := recover(); err != nil {
			core.LogPnc.Errorf("daemonCommand start:%+v", err)
			core.LogPnc.Errorf("%s", string(debug.Stack()))
		}
	}()
	println("start:" + c.Alias())
	if err := c.config(); err != nil {
		return err
	}
	if c.conf.Workspace == "" {
		return errors.New("workspace is empty")
	}
	logd := filepath.Join(c.conf.Workspace, "logs", c.conf.Name)
	err := os.MkdirAll(logd, 0755)
	if err != nil {
		return err
	}
	core.InitLog(logd)
	return runner.StartManager(c.conf)
}
func (c *daemonCommand) getFileConf() map[string]*comm.ExecerConfig {
	rt := make(map[string]*comm.ExecerConfig)
	flpth := filepath.Join(c.path, "config.yml")
	yfl, err := ioutil.ReadFile(flpth)
	if err != nil {
		//println("getFileConf ReadFile err:" + err.Error())
		return rt
	}
	err = yaml.Unmarshal(yfl, &rt)
	if err != nil {
		//println("getFileConf yaml err:" + err.Error())
		return rt
	}
	return rt
}

func (c *daemonCommand) saveFileConf(cfs map[string]*comm.ExecerConfig) {
	flpth := filepath.Join(c.path, "config.yml")
	bts, err := yaml.Marshal(cfs)
	if err != nil {
		println("saveFileConf yaml err:" + err.Error())
		return
	}
	ioutil.WriteFile(flpth, bts, 0640)
}
